using System;
using System.ComponentModel;
using System.Windows.Forms;
using AntEater.ComponentModel;
using AntEater.ComponentModel.BuildElements;

namespace AntEater.Runtime.UI
{
    /// <summary>
    /// Displays the AntEater Project in a TreeView.
    /// </summary>
    internal partial class TargetExecutionTreeView : TreeView
    {
        public event EventHandler<EventArgs> ExecuteBuildFile;
        public event EventHandler<EventArgs> AddBuildFile;
        public event EventHandler<EventArgs> RemoveBuildFile;
        public event EventHandler<EventArgs> EditExternalBuildProperties;
        public event EventHandler<EventArgs> Refreshing;
        public event EventHandler<BuildFileViewEventArgs> OpenFile;

        /// <summary>
        /// Initializes a new instance of the <see cref="TargetExecutionTreeView"/> class.
        /// </summary>
        public TargetExecutionTreeView() {
            InitializeComponent();
            
            contextMenu.ImageList = contextMenuImageList;
            editExternalBuildPropertiesMenuItem.ImageKey = "ExternalBuildProperty";
            executeBuildFileMenuItem.ImageKey = "BuildFileExecute";
            addBuildFileMenuItem.ImageKey = "BuildFileAdd";
            removeBuildFileMenuItem.ImageKey = "BuildFileRemove";
            refreshMenuItem.ImageKey = "Refresh";
            openAsBuildFileMenuItem.ImageKey = "DesignerView";
            openAsXmlMenuItem.ImageKey = "CodeView";
        }

        private Options _options;

        /// <summary>
        /// Gets or sets the options.
        /// </summary>
        /// <value>The options.</value>
        public Options Options {
            get { return _options; }
            set { _options = value; }
        }

        private Project _project;

        /// <summary>
        /// Gets or sets the project.
        /// </summary>
        /// <value>The project.</value>
        public Project Project {
            get { return _project; }
            set { _project = value; }
        }

        private BuildFile _selectedBuildFile;

        /// <summary>
        /// Gets the selected build file.
        /// </summary>
        /// <value>The selected build file.</value>
        public BuildFile SelectedBuildFile {
            get { return _selectedBuildFile; }
        }

        private TargetBuildElement _selectedTarget;

        /// <summary>
        /// Gets the selected target.
        /// </summary>
        /// <value>The selected target.</value>
        public TargetBuildElement SelectedTarget {
            get { return _selectedTarget; }
        }

        /// <summary>
        /// Forces the control to invalidate its client area and immediately redraw itself and any child controls.
        /// </summary>
        /// <PermissionSet><IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/><IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/></PermissionSet>
        public override void Refresh() {

            // Save selection of tree view
            string key = string.Empty;
            if (this.SelectedNode != null) {
                key = this.SelectedNode.Name;
            }

            // Clear treeview
            this.Nodes.Clear();

            // Add root node
            TreeNode node = new TargetExecutionProjectTreeNode(_project, _options);
            this.Nodes.Add(node);

            // Restore selection of tree view
            if (!string.IsNullOrEmpty(key)) {
                TreeNode[] nodes = this.Nodes.Find(key, true);
                if (nodes.Length > 0) {
                    this.SelectedNode = nodes[0];
                }
            }

            base.Refresh();
        }

        /// <summary>
        /// Nodes the selected.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.TreeViewEventArgs"/> instance containing the event data.</param>
        private void NodeSelected(object sender, TreeViewEventArgs e) {

            // Set selected Build File and Target
            _selectedBuildFile = null;
            _selectedTarget = null;

            if (e.Node is TargetExecutionBuildFileTreeNode) {
                _selectedBuildFile = ((TargetExecutionBuildFileTreeNode)e.Node).BuildFile;
            } else if (e.Node is TargetExecutionTargetTreeNode) {
                _selectedTarget = ((TargetExecutionTargetTreeNode)e.Node).Target;
                _selectedBuildFile = ((TargetExecutionTargetTreeNode)e.Node).BuildFile;
            }

            base.Refresh();
        }

        /// <summary>
        /// Menus the opening.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
        private void MenuOpening(object sender, CancelEventArgs e) {
            executeBuildFileMenuItem.Enabled = _selectedBuildFile != null;
            removeBuildFileMenuItem.Enabled = _selectedBuildFile != null;
            addBuildFileMenuItem.Enabled = AntEaterRuntime.Instance.Solution.BuildFiles.Count > 0;
            editExternalBuildPropertiesMenuItem.Enabled = AntEaterRuntime.Instance.Solution.IsOpen;
            openAsBuildFileMenuItem.Enabled = _selectedBuildFile != null;
            openAsXmlMenuItem.Enabled = _selectedBuildFile != null;
        }

        /// <summary>
        /// Menus the item clicked.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.ToolStripItemClickedEventArgs"/> instance containing the event data.</param>
        private void MenuItemClicked(object sender, ToolStripItemClickedEventArgs e) {

            if (e.ClickedItem == executeBuildFileMenuItem) {
                this.OnExecuteBuildFile();
            } else if (e.ClickedItem == removeBuildFileMenuItem) {
                this.OnRemoveBuildFile();
            } else if (e.ClickedItem == addBuildFileMenuItem) {
                this.OnAddBuildFile();
            } else if (e.ClickedItem == editExternalBuildPropertiesMenuItem) {
                this.OnEditExternalBuildProperties();
            } else if (e.ClickedItem == refreshMenuItem) {
                this.OnRefreshing();
            } else if (e.ClickedItem == openAsBuildFileMenuItem) {
                this.OnOpenFile(this, new BuildFileViewEventArgs(_selectedBuildFile.BuildFilePath, BuildFileViewType.Designer));
            } else if (e.ClickedItem == openAsXmlMenuItem) {
                this.OnOpenFile(this, new BuildFileViewEventArgs(_selectedBuildFile.BuildFilePath, BuildFileViewType.Xml));
            }

        }

        /// <summary>
        /// Called when [execute build file].
        /// </summary>
        private void OnExecuteBuildFile() {
            if (this.ExecuteBuildFile != null) {
                this.ExecuteBuildFile(this, new EventArgs());
            }
        }

        /// <summary>
        /// Called when [add build file].
        /// </summary>
        private void OnAddBuildFile() {
            if (this.AddBuildFile != null) {
                this.AddBuildFile(this, new EventArgs());
            }
        }

        /// <summary>
        /// Called when [remove build file].
        /// </summary>
        private void OnRemoveBuildFile() {
            if (this.RemoveBuildFile != null) {
                this.RemoveBuildFile(this, new EventArgs());
            }
        }

        /// <summary>
        /// Called when [edit external build properties].
        /// </summary>
        private void OnEditExternalBuildProperties() {
            if (this.EditExternalBuildProperties != null) {
                this.EditExternalBuildProperties(this, new EventArgs());
            }
        }

        /// <summary>
        /// Called when [refresh].
        /// </summary>
        private void OnRefreshing() {
            if (this.Refreshing != null) {
                this.Refreshing(this, new EventArgs());
            }
        }

        /// <summary>
        /// Mouses the clicked.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void MousClicked(object sender, MouseEventArgs e) {
            if (e.Button == MouseButtons.Right) {
                TreeNode node = this.GetNodeAt(e.Location);
                if (node != null) {
                    this.SelectedNode = node;
                }
            }
        }

        /// <summary>
        /// Called when [open file].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="AntEater.Runtime.UI.BuildFileViewEventArgs"/> instance containing the event data.</param>
        private void OnOpenFile(object sender, BuildFileViewEventArgs e) {
            if (this.OpenFile != null) {
                this.OpenFile(sender, e);
            }
        }
    }
}
